﻿using System;
using System.Collections.Generic;
using JTLeigh.Commerce.Spencer.Core.Common;

namespace JTLeigh.Commerce.Spencer.Core.Business
{

    /// <summary>
    /// <see langword="static" /> methods for paginating items.
    /// </summary>
    public static class PaginationTools
    {

        /// <summary>
        /// Paginates a list of items.
        /// </summary>
        /// <typeparam name="T">The type of item being paginated.</typeparam>
        /// <param name="items">The <see cref="IList{T}"/> of items to be paginate.</param>
        /// <param name="currentPage">The current page number.</param>
        /// <param name="maximumPages">The maximum number of pages.</param>
        /// <param name="maximumItemsPerPage">The maximum number of items per page.</param>
        /// <returns>A <see cref="PaginationResult{T}"/> representing the results of the 
        /// pagination.</returns>
        public static PaginationResult<T> Paginate<T>(IList<T> items, int currentPage, int maximumPages, int maximumItemsPerPage)
        {
            int startIndex;
            int finishIndex;
            int totalPages;
            List<T> itemsOnCurrentPage;

            Safety.AssertArgumentNotNull("items", items);
            Safety.AssertInRange(currentPage, 1, Int32.MaxValue, "currentPage must be between 1 and Int32.MaxValue.");
            Safety.AssertInRange(maximumPages, 1, Int32.MaxValue, "maximumPages must be between 1 and Int32.MaxValue.");
            Safety.AssertInRange(maximumItemsPerPage, 1, Int32.MaxValue, "maximumItemsPerPage must be between 1 and Int32.MaxValue.");
            Safety.AssertInRange(currentPage, 1, maximumPages, "currentPage must be between 1 and maximumPages.");

            totalPages = items.Count / maximumItemsPerPage;
            if ((items.Count % maximumItemsPerPage) > 0)
            {
                totalPages++;
            }
            if (totalPages < 1)
            {
                totalPages = 1;
            }
            if (totalPages > maximumPages)
            {
                totalPages = maximumPages;
            }

            if (currentPage > totalPages)
            {
                currentPage = totalPages;
            }

            itemsOnCurrentPage = new List<T>(maximumItemsPerPage);
            startIndex = (currentPage - 1) * maximumItemsPerPage;
            finishIndex = startIndex + maximumItemsPerPage;
            if (finishIndex > items.Count)
            {
                finishIndex = items.Count;
            }
            for (int i = startIndex; i < finishIndex; i++)
            {
                itemsOnCurrentPage.Add(items[i]);
            }

            return new PaginationResult<T>(currentPage, itemsOnCurrentPage, totalPages);
        }

    }
}
